<?php
/**
 * @author thanh.dang
 */

class Libs_Menu
{
	private static $instance;
	private $default_root_name = 'root';
	
	private static $cache;
	
	private function __construct(){
		
	}
	
	public static function getInstance(){
		if(!isset(self::$instance)){
			self::$instance = new Libs_Menu();
		}
		return self::$instance;
	}
	
	public function getMenuById($id) {
		return MenuTable::getInstance()->findOneById($id);
	}

	public function getMenuBySlug($slug)
	{
		return MenuTable::getInstance()->findOneBySlug($slug);
	}
	
	public function getRoot(){
		$root = MenuTable::getInstance()->getTree()->fetchRoot();
		if(!$root){
			//create default root item
			$root = new Menu();
			$root->name = $this->default_root_name;
			$root->save();
			MenuTable::getInstance()->getTree()->createRoot($root);
		}
		
		return $root;
	}
	
	public function saveMenu($formData,$isNew = true){
		if($isNew){
			return $this->createNewMenuItem($formData);
		}else{
			return $this->updateMenuIitem($formData);
		}
	}
	
	public function createNewMenuItem($formData){
		
		$parent_id = $formData['parent_id'];
		
		if(is_null($parent_id) || empty ($parent_id) || !is_numeric($parent_id)){
			$parent = self::getRoot();
		}else{
			$parent = self::getMenuById($parent_id);
		}
		
		if(!$parent)
			return new Error(array(
				'error' => "An error occured."
			));
		
		$menu = new Menu();
		try{
			$menu->setArray(Arr::extract($formData,array('name','link','target')));
			$menu->active = is_null(Arr::get($formData, 'active')) ? 0 : Arr::get($formData, 'active');
			$menu->save();
            
            $menu->getNode()->insertAsLastChildOf($parent);
            
            if(!is_null($formData['target_id']) && is_numeric($formData['target_id']))
            {
                $this->moveMenu($menu->id,$formData['target_id'],$formData['position']);
            }
            
			return $menu;
		}catch (Doctrine_Validator_Exception $ex){
			return new Error($menu->getErrorStack());
		}catch (Doctrine_Exception $de){
			
		}
	}
	
	public function updateMenuIitem($formData){

		//if we don't find any id field in var post --> oops error
		if(isset($formData['id']) && is_numeric($formData['id'])){
			$menu = self::getMenuById($formData['id']);
			if(!$menu)
				return new Error();

			try{
                
				$menu->fromArray($formData);
				$menu->active = is_null(Arr::get($formData, 'active')) ? 0 : Arr::get($formData, 'active');
                
                $menu->save();
                
                if(!is_null($formData['target_id']) && is_numeric($formData['target_id']))
                {
                    $this->moveMenu($menu->id,$formData['target_id'],$formData['position']);
                }
				return $menu;
				
			}catch (Doctrine_Validator_Exception $ex){
				return new Error($menu->getErrorStack());				
			}
			
		}else{
			//not found menu id
			return new Error(array('error' => 'An error occured.'));
		}
	}
	
	public function getMenusAsArray($active = true){
		$root = $this->getRoot();
		
		if(!isset(self::$cache[$root->name])){
			
			$menus = Doctrine_Query::create()
									->from('Menu m')
									->where('m.level > 0')
									->addWhere('m.active = ?',$active)
									->orderBy('m.lft ASC')->execute();
			
			//$descendants = $root->getNode()->getDescendants();
    		//self::$cache[$root->name] =(!$descendants) ? array() : $descendants->toArray();
    		self::$cache[$root->name] = $menus ? $menus->toArray() : array();
    	}
    	
    	return self::$cache[$root->name];
	}
	
	public function getMenuAsTree()
	{
		$list = $this->getMenusAsArray();
		return Libs_Category::getInstance()->parseTree($list);
	}
	
	public function renderTopHtmlMenu($menus)
	{
		$html = '<ul>';
		
		foreach($menus as $menu){
            
            if(!Valid::url($menu['link']))
                $menu['link'] = Url::base().$menu['link'];
            
			$html .= "<li><a target='".$menu['target']."' href='".$menu['link']."'><span>".$menu['name']."</span></a>";

			if(isset($menu['children'])){
				$html .= $this->renderTopHtmlMenu($menu['children']);
			}

			$html .= "</li>";
		}

		return $html.'</ul>';
	}
    
    public function renderFooterHtmlMenu($menus)
    {
        $html = '<div id="menu_link">';
		foreach($menus as $menu){
            
            if(!Valid::url($menu['link']))
                $menu['link'] = Url::base().$menu['link'];
            
			$html .= "<a target='".$menu['target']."' href='".$menu['link']."'><span>".$menu['name']."</span></a>";
            
            /*
			if(isset($menu['children'])){
				$html .= $this->renderHtmlMenu($menu['children']);
			}
			$html .= "</li>";
             * 
             */
		}

		return $html.'</div>';
    }
    
    /**
     * Move A Category To Another Category
     * $catId : id category was moved
     * $targetId : id target category which was moved to
     * $position : sibling ( before, after ) | inside (as last child)
     * 
     * @return return false if not success
     */
    public function moveMenu($menuId,$targetId,$position)
    {
        $menu = Libs_Menu::getInstance()->getMenuById($menuId);
        if(!$menu)
            return false;
        
        $target = Libs_Menu::getInstance()->getMenuById($targetId);
        
        if(!$target)
            return false;
        
        switch ($position)
        {
            case 'before':
                $menu->getNode()->moveAsPrevSiblingOf($target);
                break;
            case 'after':
            default:
                $menu->getNode()->moveAsNextSiblingOf($target);
                break;
            case 'inside':
                $menu->getNode()->moveAsLastChildOf($target);
                break;
        }
    }
}
